package cn.iocoder.yudao.module.search.service.search.impl;

import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.search.api.search.dto.*;
import cn.iocoder.yudao.module.search.tenant.IndexNamingStrategy;
import cn.iocoder.yudao.module.search.tenant.PlanetFilter;
import cn.iocoder.yudao.module.search.service.engine.SearchEngine;
import cn.iocoder.yudao.module.search.service.search.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 搜索服务实现类
 * 支持多租户索引隔离和星球字段过滤
 * 
 * @author 芋道源码
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SearchServiceImpl implements SearchService {

    private final SearchEngine searchEngine;

    // ========== 索引管理 ==========

    @Override
    public Boolean createIndex(SearchIndexReqDTO reqDTO) {
        Long tenantId = TenantContextHolder.getTenantId();
        log.info("[createIndex][创建索引] tenantId: {}, indexName: {}", tenantId, reqDTO.getIndexName());
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, reqDTO.getIndexName());
        
        // 创建新的请求对象，使用租户索引名称
        SearchIndexReqDTO tenantReqDTO = new SearchIndexReqDTO();
        tenantReqDTO.setIndexName(tenantIndexName);
        tenantReqDTO.setMapping(reqDTO.getMapping());
        tenantReqDTO.setSettings(reqDTO.getSettings());
        
        return searchEngine.createIndex(tenantReqDTO);
    }

    @Override
    public Boolean deleteIndex(Long tenantId, String indexName) {
        log.info("[deleteIndex][删除索引] tenantId: {}, indexName: {}", tenantId, indexName);
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, indexName);
        return searchEngine.deleteIndex(tenantIndexName);
    }

    @Override
    public Boolean existsIndex(Long tenantId, String indexName) {
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, indexName);
        return searchEngine.existsIndex(tenantIndexName);
    }

    @Override
    public SearchIndexRespDTO getIndex(Long tenantId, String indexName) {
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, indexName);
        SearchIndexRespDTO result = searchEngine.getIndex(tenantIndexName);
        
        // 将租户索引名称转换回原始索引名称
        if (result != null) {
            result.setIndexName(indexName);
        }
        
        return result;
    }

    @Override
    public List<SearchIndexRespDTO> listIndexes(Long tenantId) {
        // 获取租户的所有索引
        List<SearchIndexRespDTO> allIndexes = searchEngine.listIndexes();
        
        // 过滤出属于当前租户的索引
        return allIndexes.stream()
                .filter(index -> IndexNamingStrategy.isTenantIndex(index.getIndexName()))
                .filter(index -> IndexNamingStrategy.extractTenantId(index.getIndexName()).equals(tenantId))
                .map(index -> {
                    // 将租户索引名称转换回原始索引名称
                    String originalIndexName = IndexNamingStrategy.extractOriginalIndexName(index.getIndexName());
                    index.setIndexName(originalIndexName);
                    return index;
                })
                .collect(Collectors.toList());
    }

    // ========== 文档管理 ==========

    @Override
    public String createDocument(SearchDocumentReqDTO reqDTO) {
        Long tenantId = TenantContextHolder.getTenantId();
        log.info("[createDocument][创建文档] tenantId: {}, planetId: {}, indexName: {}", 
                tenantId, reqDTO.getPlanetId(), reqDTO.getIndexName());
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, reqDTO.getIndexName());
        
        // 为文档添加星球ID字段
        Map<String, Object> document = PlanetFilter.addPlanetId(reqDTO.getDocument(), reqDTO.getPlanetId());
        
        // 创建新的请求对象
        SearchDocumentReqDTO tenantReqDTO = new SearchDocumentReqDTO();
        tenantReqDTO.setPlanetId(reqDTO.getPlanetId());
        tenantReqDTO.setIndexName(tenantIndexName);
        tenantReqDTO.setDocumentId(reqDTO.getDocumentId());
        tenantReqDTO.setDocument(document);
        
        return searchEngine.createDocument(tenantReqDTO);
    }

    @Override
    public Boolean updateDocument(SearchDocumentReqDTO reqDTO) {
        Long tenantId = TenantContextHolder.getTenantId();
        log.info("[updateDocument][更新文档] tenantId: {}, planetId: {}, indexName: {}, documentId: {}", 
                tenantId, reqDTO.getPlanetId(), reqDTO.getIndexName(), reqDTO.getDocumentId());
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, reqDTO.getIndexName());
        
        // 为文档添加星球ID字段
        Map<String, Object> document = PlanetFilter.addPlanetId(reqDTO.getDocument(), reqDTO.getPlanetId());
        
        // 创建新的请求对象
        SearchDocumentReqDTO tenantReqDTO = new SearchDocumentReqDTO();
        tenantReqDTO.setPlanetId(reqDTO.getPlanetId());
        tenantReqDTO.setIndexName(tenantIndexName);
        tenantReqDTO.setDocumentId(reqDTO.getDocumentId());
        tenantReqDTO.setDocument(document);
        
        return searchEngine.updateDocument(tenantReqDTO);
    }

    @Override
    public Boolean deleteDocument(Long tenantId, String indexName, String documentId) {
        log.info("[deleteDocument][删除文档] tenantId: {}, indexName: {}, documentId: {}", 
                tenantId, indexName, documentId);
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, indexName);
        return searchEngine.deleteDocument(tenantIndexName, documentId);
    }

    @Override
    public SearchDocumentRespDTO getDocument(Long tenantId, String indexName, String documentId) {
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, indexName);
        SearchDocumentRespDTO result = searchEngine.getDocument(tenantIndexName, documentId);
        
        // 将租户索引名称转换回原始索引名称
        if (result != null) {
            result.setIndexName(indexName);
        }
        
        return result;
    }

    @Override
    public SearchBulkRespDTO bulkDocument(SearchBulkReqDTO reqDTO) {
        Long tenantId = TenantContextHolder.getTenantId();
        log.info("[bulkDocument][批量操作文档] tenantId: {}, planetId: {}, indexName: {}", 
                tenantId, reqDTO.getPlanetId(), reqDTO.getIndexName());
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, reqDTO.getIndexName());
        
        // 为所有文档添加星球ID字段
        List<SearchBulkReqDTO.BulkOperation> operations = reqDTO.getOperations().stream()
                .map(operation -> {
                    SearchBulkReqDTO.BulkOperation newOperation = new SearchBulkReqDTO.BulkOperation();
                    newOperation.setOperation(operation.getOperation());
                    newOperation.setDocumentId(operation.getDocumentId());
                    
                    // 为文档添加星球ID字段
                    if (operation.getDocument() instanceof Map) {
                        @SuppressWarnings("unchecked")
                        Map<String, Object> document = (Map<String, Object>) operation.getDocument();
                        Map<String, Object> documentWithPlanet = PlanetFilter.addPlanetId(document, reqDTO.getPlanetId());
                        newOperation.setDocument(documentWithPlanet);
                    } else {
                        newOperation.setDocument(operation.getDocument());
                    }
                    
                    return newOperation;
                })
                .collect(Collectors.toList());
        
        // 创建新的请求对象
        SearchBulkReqDTO tenantReqDTO = new SearchBulkReqDTO();
        tenantReqDTO.setPlanetId(reqDTO.getPlanetId());
        tenantReqDTO.setIndexName(tenantIndexName);
        tenantReqDTO.setOperations(operations);
        
        return searchEngine.bulkDocument(tenantReqDTO);
    }

    // ========== 搜索查询 ==========

    @Override
    public SearchQueryRespDTO search(SearchQueryReqDTO reqDTO) {
        Long tenantId = TenantContextHolder.getTenantId();
        log.info("[search][搜索查询] tenantId: {}, planetId: {}, indexName: {}, query: {}", 
                tenantId, reqDTO.getPlanetId(), reqDTO.getIndexName(), reqDTO.getQuery());
        
        // 构建租户索引名称
        String tenantIndexName = IndexNamingStrategy.buildTenantIndexName(tenantId, reqDTO.getIndexName());
        
        // 创建新的请求对象
        SearchQueryReqDTO tenantReqDTO = new SearchQueryReqDTO();
        tenantReqDTO.setPlanetId(reqDTO.getPlanetId());
        tenantReqDTO.setIndexName(tenantIndexName);
        tenantReqDTO.setQuery(reqDTO.getQuery());
        tenantReqDTO.setFields(reqDTO.getFields());
        tenantReqDTO.setSorts(reqDTO.getSorts());
        tenantReqDTO.setPageNo(reqDTO.getPageNo());
        tenantReqDTO.setPageSize(reqDTO.getPageSize());
        tenantReqDTO.setHighlightFields(reqDTO.getHighlightFields());
        tenantReqDTO.setAggregations(reqDTO.getAggregations());
        
        // 添加星球过滤条件
        Map<String, Object> filters = PlanetFilter.addPlanetFilter(reqDTO.getFilters(), reqDTO.getPlanetId());
        tenantReqDTO.setFilters(filters);
        
        SearchQueryRespDTO result = searchEngine.search(tenantReqDTO);
        
        // 将租户索引名称转换回原始索引名称
        if (result != null && result.getDocuments() != null) {
            result.getDocuments().forEach(doc -> {
                if (doc.getIndexName() != null) {
                    doc.setIndexName(reqDTO.getIndexName());
                }
            });
        }
        
        return result;
    }

}
